// webgl renderer

import { useEffect, useRef } from 'react';

const VERTEX_SOURCE = `
attribute vec4 a_position;

void main() {
  gl_Position = a_position;
}
`;

const FRAGMENT_SOURCE = `
precision mediump float;

void main() {
  gl_FragColor = vec4(1, 0, 0.5, 1);
}
`;

function createShader(gl: WebGLRenderingContext, type: GLenum, source: string) {
  const shader = gl.createShader(type);
  if (!shader) throw new Error('Fail to create shader');

  gl.shaderSource(shader, source);
  gl.compileShader(shader);

  const success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
  if (success) return shader;

  const msg = gl.getShaderInfoLog(shader) || 'Shader compile error';
  gl.deleteShader(shader);
  throw new Error(msg);
}

function createProgram(
  gl: WebGLRenderingContext,
  vertexShader: WebGLShader,
  fragmentShader: WebGLShader
) {
  const program = gl.createProgram();
  gl.attachShader(program, vertexShader);
  gl.attachShader(program, fragmentShader);
  gl.linkProgram(program);

  const success = gl.getProgramParameter(program, gl.LINK_STATUS);
  if (success) return program;

  const msg = gl.getProgramInfoLog(program) || 'Program link error';
  gl.deleteProgram(program);
  throw new Error(msg);
}

export function Renderer() {
  const canvasRef = useRef<HTMLCanvasElement | null>(null);

  useEffect(() => {
    const canvas = canvasRef.current;
    if (canvas) {
      const gl = canvas.getContext('webgl');
      if (gl) {
        const vertexShader = createShader(gl, gl.VERTEX_SHADER, VERTEX_SOURCE);
        const fragmentShader = createShader(
          gl,
          gl.FRAGMENT_SHADER,
          FRAGMENT_SOURCE
        );
        const program = createProgram(gl, vertexShader, fragmentShader);

        const positionAttributeLocation = gl.getAttribLocation(
          program,
          'a_position'
        );
        const positionBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);

        const positions = [0, 0, 0, 0.5, 0.7, 0];
        gl.bufferData(
          gl.ARRAY_BUFFER,
          new Float32Array(positions),
          gl.STATIC_DRAW
        );
      }
    }

    return function () {};
  }, []);

  return <canvas></canvas>;
}
